﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FinPlusCommon;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;

namespace FinPlusComponents
{
    public class QLAnalytics : FinPlusComponent
    {
        public override string Id { get; set; }
        public override string[] States { get { return new string[] { }; } }
        public override string[] TestStates { get { return new string[] { "ModelTest", "IsValid" }; } }
        public override IFinPlusFunctions Model { get { return _instrumentConn.Model; } }
        public override string ModelTest { get { return Model.ToString(); } }
        public override bool IsValid { get; set; }

        public ql QL { get { return _ql; } } 
        public string MarketName { get; private set; }
        public string CacheName { get; private set; }
        public string DiscountCurve { get; private set; }
        public int AsOf { get; private set; }
        public string BuySell { get; private set; }
        public IDictionary<string, string> Infos { get; private set; }
        public IDictionary<string, string> Controls { get; private set; }
        public IDictionary<string, int> Shocks { get; private set; }
        public string ControlString { get; set; }
        public bool HasControlString { get; set; }

        private enum DockControls { FinPlusDataConn, FinPlusChildService, FinPlusMarket, Default }
        private enum Connection { Instruments, Default, Exception }
        private enum Params { LevelUpdate, Request, Resend, Refresh, Shock }
        private IFinPlusComponent _instrumentConn;
        private static ql _ql = new ql();
        private static IFinPlusFunction _func;
        private bool _hasInitialised;
        
        //construct
        public QLAnalytics(string marketName, string cacheName, string asOf, string discountCurve, string buySell, string infoString,  string controlString, string shocks) 
        {
            MarketName = marketName;
            CacheName = cacheName;
            BuySell = buySell;
            DiscountCurve = discountCurve;
            AsOf = int.Parse(asOf);
            Infos = u.ToDictionary(infoString, true);
            Controls = u.ToDictionary(controlString, true);
            ControlString = string.Join(",", Controls.Select(f => f.Key).ToArray());
            HasControlString = !string.IsNullOrEmpty(ControlString);
            if (shocks != string.Empty) Shocks = u.Replace(shocks).Split(';').ToDictionary(f => f.Split(':')[0], f => int.Parse(f.Split(':')[1]));
        }

        //common control interface
        public override void Dock(object component, string dock) 
        {
            try
            {
                switch (u.EnumTryParse<DockControls>(component.GetType().Name, DockControls.Default))
                {
                    case DockControls.FinPlusMarket:
                    case DockControls.FinPlusChildService:
                    case DockControls.FinPlusDataConn:
                    case DockControls.Default: AddConnection((IFinPlusComponent)component, dock); break;
                }
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        public override void Initialise()
        {
            if (_hasInitialised || _instrumentConn == null) return;

            lock (QL)
                QL.MarketSet(MarketName, AsOf);

            if (_func == null) _func = new Function("QL", "ql") { Object = QL, Type = QL.GetType() };

            IsValid = _hasInitialised = true;
        }

        public override void CommandRouter(IFinPlusFunction func) { }

        public override void Dispose() 
        {
            if (_instrumentConn != null)
                _instrumentConn.Dispose();
        }

        public string InvokeMethod(IFinPlusFunction func, IList<string> exclude = null)
        {
            var res = FinPlusAssembler.InvokeMethod(func, _func, null, exclude, true);
            return res.ToString();
        }

        //private
        private void AddConnection(IFinPlusComponent conn, string dock)
        {
            switch (u.EnumTryParse<Connection>(dock, Connection.Exception))
            {
                case Connection.Instruments: _instrumentConn = conn; break;
                case Connection.Default: conn.Dock(this, null); break;
            }
        }
    }
}
